package com.example.smartpark.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.smartpark.dto.ChangePasswordDTO;
import com.example.smartpark.dto.UserLoginDTO;
import com.example.smartpark.dto.UserProfileUpdateDTO;
import com.example.smartpark.dto.UserRegisterDTO;
import com.example.smartpark.dto.VehicleAddDTO;
import com.example.smartpark.dto.VehicleUpdateDTO;
import com.example.smartpark.exception.BusinessException;
import com.example.smartpark.mapper.UserMapper;
import com.example.smartpark.model.User;
import com.example.smartpark.service.UserService;
import com.example.smartpark.service.VehicleService;
import com.example.smartpark.utils.JwtUtils;
import com.example.smartpark.utils.MD5Utils;
import com.example.smartpark.vo.LoginVO;
import com.example.smartpark.vo.UserVO;
import com.example.smartpark.vo.VehicleVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 用户服务实现类
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private VehicleService vehicleService;

    /**
     * 用户注册
     *
     * @param registerDTO 注册信息
     * @return 注册结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserVO register(UserRegisterDTO registerDTO) {
        log.info("用户注册: {}", registerDTO.getUsername());
        
        // 检查用户名是否已存在
        if (checkUsernameExists(registerDTO.getUsername())) {
            throw new BusinessException("用户名已存在");
        }
        
        // 创建用户对象
        User user = new User();
        // 复制注册信息到用户对象（除了密码）
        BeanUtils.copyProperties(registerDTO, user);
        
        // 密码加密
        String encryptedPassword = MD5Utils.encrypt(registerDTO.getPassword());
        log.info("注册密码加密: 原密码={}, 加密后={}", registerDTO.getPassword(), encryptedPassword);
        user.setPassword(encryptedPassword);
        
        // 设置默认属性
        user.setAvatar("/custom-avatar.png");
        user.setRole(0); // 默认为普通用户
        user.setStatus(1); // 默认为启用状态
        
        // 保存用户
        if (!save(user)) {
            throw new BusinessException("注册失败");
        }
        
        // 转换为VO对象并返回
        return convertToUserVO(user);
    }

    /**
     * 用户登录
     *
     * @param loginDTO 登录信息
     * @return 登录结果（包含token和用户信息）
     */
    @Override
    public LoginVO login(UserLoginDTO loginDTO) {
        log.info("用户登录: {}", loginDTO.getUsername());
        
        try {
            // 根据用户名查询用户
            User user = getByUsername(loginDTO.getUsername());
            
            // 用户不存在
            if (user == null) {
                throw new BusinessException("用户名或密码错误");
            }
            
            // 记录用户信息和密码
            log.info("找到用户: {}, 密码密文: {}", user.getUsername(), user.getPassword());
            
            // 对输入的密码进行加密
            String encryptedPassword = MD5Utils.encrypt(loginDTO.getPassword());
            log.info("登录密码加密: 原密码={}, 加密后={}", loginDTO.getPassword(), encryptedPassword);
            
            // 比较密码是否匹配
            boolean passwordMatches = user.getPassword().equals(encryptedPassword);
            log.info("密码比较结果: {}", passwordMatches);
            
            if (!passwordMatches) {
                throw new BusinessException("用户名或密码错误");
            }
            
            // 检查用户状态
            if (user.getStatus() == 0) {
                throw new BusinessException("账号已被禁用");
            }
            
            // 更新最后登录时间
            updateLastLogin(user.getId());
            
            // 生成JWT令牌
            String token = JwtUtils.generateToken(user.getId());
            
            // 转换为VO对象
            UserVO userVO = convertToUserVO(user);
            
            // 返回登录结果
            return new LoginVO(token, userVO);
        } catch (BusinessException e) {
            throw e;  // 业务异常直接抛出
        } catch (Exception e) {
            log.error("登录过程中发生错误", e);
            throw new BusinessException("登录失败：" + e.getMessage());
        }
    }

    /**
     * 根据用户ID获取用户信息
     *
     * @param userId 用户ID
     * @return 用户信息
     */
    @Override
    public UserVO getUserInfo(Integer userId) {
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        return convertToUserVO(user);
    }

    /**
     * 根据用户名查询用户
     *
     * @param username 用户名
     * @return 用户信息
     */
    @Override
    public User getByUsername(String username) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        return getOne(queryWrapper);
    }

    /**
     * 检查用户名是否已存在
     *
     * @param username 用户名
     * @return 是否存在
     */
    @Override
    public boolean checkUsernameExists(String username) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        return count(queryWrapper) > 0;
    }

    /**
     * 更新最后登录时间
     *
     * @param userId 用户ID
     */
    @Override
    public void updateLastLogin(Integer userId) {
        baseMapper.updateLastLogin(userId);
    }
    
    /**
     * 获取用户个人资料
     *
     * @param userId 用户ID
     * @return 用户资料视图对象
     */
    @Override
    public UserVO getUserProfile(Integer userId) {
        log.info("获取用户个人资料: userId={}", userId);
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        return convertToUserVO(user);
    }
    
    /**
     * 更新用户个人资料
     *
     * @param userId 用户ID
     * @param profileUpdateDTO 用户资料更新DTO
     * @return 更新后的用户资料视图对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserVO updateUserProfile(Integer userId, UserProfileUpdateDTO profileUpdateDTO) {
        log.info("更新用户个人资料: userId={}, 更新数据={}", userId, profileUpdateDTO);
        
        // 获取当前用户
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 更新用户信息
        boolean needsUpdate = false;
        
        if (profileUpdateDTO.getRealName() != null && !profileUpdateDTO.getRealName().equals(user.getRealName())) {
            user.setRealName(profileUpdateDTO.getRealName());
            needsUpdate = true;
        }
        
        if (profileUpdateDTO.getPhone() != null && !profileUpdateDTO.getPhone().equals(user.getPhone())) {
            user.setPhone(profileUpdateDTO.getPhone());
            needsUpdate = true;
        }
        
        if (profileUpdateDTO.getEmail() != null && !profileUpdateDTO.getEmail().equals(user.getEmail())) {
            user.setEmail(profileUpdateDTO.getEmail());
            needsUpdate = true;
        }
        
        if (profileUpdateDTO.getAvatar() != null && !profileUpdateDTO.getAvatar().equals(user.getAvatar())) {
            user.setAvatar(profileUpdateDTO.getAvatar());
            needsUpdate = true;
        }
        
        // 如果有字段更新，则保存用户信息
        if (needsUpdate) {
            if (!updateById(user)) {
                throw new BusinessException("更新个人资料失败");
            }
        }
        
        return convertToUserVO(user);
    }
    
    /**
     * 修改用户密码
     *
     * @param userId 用户ID
     * @param changePasswordDTO 修改密码DTO
     * @return 修改是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean changePassword(Integer userId, ChangePasswordDTO changePasswordDTO) {
        log.info("修改用户密码: userId={}", userId);
        
        // 获取当前用户
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 验证旧密码是否正确
        String encryptedOldPassword = MD5Utils.encrypt(changePasswordDTO.getOldPassword());
        if (!user.getPassword().equals(encryptedOldPassword)) {
            throw new BusinessException("旧密码不正确");
        }
        
        // 验证新密码与确认密码是否一致
        if (!changePasswordDTO.getNewPassword().equals(changePasswordDTO.getConfirmPassword())) {
            throw new BusinessException("新密码与确认密码不一致");
        }
        
        // 验证新密码不能与旧密码相同
        if (changePasswordDTO.getOldPassword().equals(changePasswordDTO.getNewPassword())) {
            throw new BusinessException("新密码不能与旧密码相同");
        }
        
        // 加密新密码
        String encryptedNewPassword = MD5Utils.encrypt(changePasswordDTO.getNewPassword());
        user.setPassword(encryptedNewPassword);
        
        // 更新密码
        return updateById(user);
    }
    
    /**
     * 获取用户车辆列表
     *
     * @param userId 用户ID
     * @return 车辆列表
     */
    @Override
    public List<VehicleVO> getUserVehicles(Integer userId) {
        return vehicleService.getUserVehicles(userId);
    }
    
    /**
     * 添加车辆
     *
     * @param userId 用户ID
     * @param vehicleAddDTO 添加车辆DTO
     * @return 添加的车辆信息
     */
    @Override
    public VehicleVO addVehicle(Integer userId, VehicleAddDTO vehicleAddDTO) {
        return vehicleService.addVehicle(userId, vehicleAddDTO);
    }
    
    /**
     * 更新车辆信息
     *
     * @param userId 用户ID
     * @param vehicleId 车辆ID
     * @param vehicleUpdateDTO 更新车辆DTO
     * @return 更新后的车辆信息
     */
    @Override
    public VehicleVO updateVehicle(Integer userId, Integer vehicleId, VehicleUpdateDTO vehicleUpdateDTO) {
        return vehicleService.updateVehicle(userId, vehicleId, vehicleUpdateDTO);
    }
    
    /**
     * 删除车辆
     *
     * @param userId 用户ID
     * @param vehicleId 车辆ID
     * @return 是否删除成功
     */
    @Override
    public boolean deleteVehicle(Integer userId, Integer vehicleId) {
        return vehicleService.deleteVehicle(userId, vehicleId);
    }

    @Override
    public BigDecimal getUserBalance(Integer userId) {
        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        return user.getBalance() != null ? user.getBalance() : BigDecimal.ZERO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BigDecimal rechargeBalance(Integer userId, BigDecimal amount) {
        if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException("充值金额必须大于0");
        }
        
        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 更新用户余额
        BigDecimal currentBalance = user.getBalance() != null ? user.getBalance() : BigDecimal.ZERO;
        BigDecimal newBalance = currentBalance.add(amount);
        
        user.setBalance(newBalance);
        user.setUpdatedAt(new Date());
        
        this.updateById(user);
        
        return newBalance;
    }

    /**
     * 将User对象转换为UserVO对象
     *
     * @param user User对象
     * @return UserVO对象
     */
    private UserVO convertToUserVO(User user) {
        if (user == null) {
            return null;
        }
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }
} 